package com.gcb.apache.http;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gcb.apache.http.CharsetHandler;

/**
 * 该类是用于，从桌酷壁纸(http://www.zhuoku.com)，采集壁纸
 * 
 * @author Cre.Gu
 * 
 */
public class PicCollector {

	private static Logger log = LoggerFactory.getLogger(PicCollector.class);

	private HttpClient client;
	private CharsetHandler charsetHandler = new CharsetHandler("gb2312");
	private static HashMap<String, List<String>> listMap;
	private static String contentUrl;
	private CountDownLatch zhuaHandlerCountDown;// 判斷線程是否結束

	public enum WebSite {
		ZHUOKU_PAGINATION, ZHUOKU_CONTENT
	}

	/**
	 * 1440x900的网址前缀
	 */
	private static final String x1440x900 = "http://tool.zhuoku.com/tool/dyw_size.php?width=1440&height=900&corp_x=center&corp_y=top&picurl=..";

	/**
	 * 1366x768的网址前缀
	 */
	private static final String x1366x768 = "http://tool.zhuoku.com/tool/dyw_size.php?width=1366&height=768&corp_x=center&corp_y=top&picurl=..";

	public PicCollector() {
		// TODO Auto-generated constructor stub
		ThreadSafeClientConnManager conman = new ThreadSafeClientConnManager();
		client = new DefaultHttpClient(conman);
	}

	/**
	 * 截取网页的url列表
	 * 
	 * @param handler
	 *            字符处理类
	 * @param url
	 *            网页路径
	 * @param linksetStart
	 *            段截取开始
	 * @param linksetEnd
	 *            段截取结束
	 * @param linkStart
	 *            连接截取开始
	 * @param linkEnd
	 *            连接截取结束
	 * @param level
	 *            截取的标准
	 * @return List<String>
	 * @author Cre.Gu at 2012-5-31
	 */
	public List<String> getContentList(HttpClient client,
			CharsetHandler handler, String url, String linksetStart,
			String linksetEnd, String linkStart, String linkEnd, WebSite site) {
		List<String> list = new ArrayList<String>();
		try {
			HttpGet httpget = new HttpGet(new URI(url));
			String html = client.execute(httpget, handler);
			int start = html.indexOf(linksetStart);
			if (start == -1) {
				return list;
			}
			start += linksetStart.length();
			int end = html.indexOf(linksetEnd, start);
			if (end == -1) {
				return list;
			}
			String s = html.substring(start, end);
			start = 0;
			String link;
			while ((start = s.indexOf(linkStart, start)) != -1) {
				start += linkStart.length();
				end = s.indexOf(linkEnd, start);
				if (end == -1) {
					return list;
				} else {
					link = s.substring(start, end);
					if (WebSite.ZHUOKU_PAGINATION == site) {
						/**
						 * 下拉列表的value拼接到完整的url
						 */
						String base = url
								.substring(0, url.lastIndexOf("/") + 1);
						link = base + link + "htm";
					} else if (WebSite.ZHUOKU_CONTENT == site) {
						/**
						 * zhuoku具体的页面
						 */
						int beginIndex = link.indexOf("img.zhuoku.com")
								+ "img.zhuoku.com".length();
						int endIndex = link.indexOf("thumbs", beginIndex);
						String link1 = link.substring(beginIndex, endIndex);
						String link2 = link.substring(link.lastIndexOf("tn_")
								+ "tn_".length());
						link = contentUrl + link1 + link2;
					}
					log.debug("content link: {}", link);
					list.add(link);
					start = end + linkEnd.length();
				}
			}
		} catch (Exception e) {
			log.warn(null, e);
		}
		return list;
	}

	public static List<String> getContentList(CharsetHandler handler,
			String url, String linksetStart, String linksetEnd,
			String linkStart, String linkEnd, String level) {
		HttpClient client = new DefaultHttpClient();
		List<String> list = new ArrayList<String>();
		try {
			HttpGet httpget = new HttpGet(new URI(url));
			String html = client.execute(httpget, handler);
			client.getConnectionManager().shutdown();
			int start = html.indexOf(linksetStart);
			if (start == -1) {
				return list;
			}
			start += linksetStart.length();
			int end = html.indexOf(linksetEnd, start);
			if (end == -1) {
				return list;
			}
			String s = html.substring(start, end);
			start = 0;
			String link;
			while ((start = s.indexOf(linkStart, start)) != -1) {
				start += linkStart.length();
				end = s.indexOf(linkEnd, start);
				if (end == -1) {
					return list;
				} else {
					link = s.substring(start, end);
					log.debug("content link: {}", link);
					list.add(link);
					start = end + linkEnd.length();
				}
			}
		} catch (Exception e) {
			log.warn(null, e);
		}
		return list;
	}

	/**
	 * 将指定url的页面保存到path路径下
	 * 
	 * @param client
	 * @param url
	 *            这里都是图片
	 * @param path
	 *            本地硬盘路径
	 * @return boolean
	 * @author Cre.Gu at 2012-6-25
	 */
	public boolean saveContent(HttpClient client, String url, String path) {
		HttpGet get = new HttpGet(url);
		url = url.substring(url.indexOf("..") + 2);
		String urlPath = url.substring(0, url.lastIndexOf("/"));
		File filePath = new File(path + urlPath);
		if (!filePath.exists()) {
			filePath.mkdirs();
		}
		File file = new File(path + url);
		if (file.exists() && file.length() > 0) {
			log.info(file.getAbsolutePath() + "文件已存在，跳过下载");
			return true;
		}
		FileOutputStream fos;
		FileChannel fic;
		try {
			fos = new FileOutputStream(file);
			fic = fos.getChannel();
			HttpResponse response = client.execute(get);
			if (response.getStatusLine().getStatusCode() == 200) {
				HttpEntity entity = response.getEntity();
				if (entity != null) {
					byte[] b = EntityUtils.toByteArray(entity);
					ByteBuffer bb = ByteBuffer.wrap(b);
					fic.write(bb);
					bb.flip();
					fic.close();
					fos.close();
					log.info(file.getAbsolutePath());
					return true;
				}
			}
			log.warn(response.getStatusLine().getStatusCode() + "");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			get.abort();
		}
		return false;
	}

	public void loadImg(String baseUrl, String path, String vga) {
		// TestHttpClient(baseUrl, path, vga);
	}

	public static void getBase() {
		List<String> list = PicCollector.getContentList(new CharsetHandler(
				"gb2312"),
				"http://www.zhuoku.com/zhuomianbizhi/jingxuan-jingxuantaotu"
						+ "/index-1.htm", "<div class=\"bizhiin\">",
				"<div class=\"lieads\">", "<a href=\"", "\" class=\"title\"",
				null);
		for (int i = 0; i < list.size(); i++) {
			String baseUrl1 = "http://www.zhuoku.com" + list.get(i);
			System.out.println(baseUrl1);
		}
	}

	public static void main(String[] args) {
		String baseUrl = "http://www.zhuoku.com/zhuomianbizhi/jingxuan-jingxuantaotu/"
				+ "20130120230149.htm";
		String vga = "1366x768";
		// String vga = "1440x900";
		String path = "F:\\快盘\\我的图片\\" + vga + "\\";
		PicCollector zhua = new PicCollector();
		zhua.zhuoku(baseUrl, path, vga);
	}

	/**
	 * 从桌酷壁纸，采集指定像素的图片
	 * 
	 * @param baseUrl
	 *            需要采集的网址
	 * @param path
	 *            保存的路径
	 * @param vga
	 *            分辨率 void
	 * @author Cre.Gu at 2012-6-25
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void zhuoku(String baseUrl, String path, String vga) {
		listMap = new HashMap<String, List<String>>();
		if ("1440x900".equals(vga)) {
			contentUrl = x1440x900;
		} else if ("1366x768".equals(vga)) {
			contentUrl = x1366x768;
		}
		try {
			/*
			 * 总共有第几页
			 */
			List<String> listUrl = this.getContentList(client, charsetHandler,
					baseUrl, "<select", "</select>", "value='", "htm'",
					WebSite.ZHUOKU_PAGINATION);
			int count = 0;
			for (int i = 0; i < listUrl.size(); i++) {
				/*
				 * 每一页，总共有多少张图片
				 */
				List<String> list = getContentList(client, charsetHandler,
						listUrl.get(i), "<div class=\"bizhiin\">",
						"<div class=\"clear\">", "<img src=", "\" alt=",
						WebSite.ZHUOKU_CONTENT);
				listMap.put(listUrl.get(i), list);
				count += list.size();
			}
			int threadSize = listUrl.size();
			System.out.println("总共有图片：" + count + "张，分成" + threadSize
					+ "个线程执行。");
			long startTime = System.currentTimeMillis();
			Iterator iter = listMap.entrySet().iterator();
			zhuaHandlerCountDown = new CountDownLatch(threadSize);
			while (iter.hasNext()) {
				Map.Entry entry = (Map.Entry) iter.next();
				log.info("开始下载：" + entry.getKey());
				List<String> list = (List<String>) entry.getValue();
				Thread thread = new Thread(new ZhuaHandler(client, list, path));
				thread.start();
				/*
				 * for (Iterator<String> iterator = list.iterator(); iterator
				 * .hasNext();) { String string = iterator.next(); if
				 * (!saveContent(client, string, path)) { log.warn("下载失败：" +
				 * string); } }
				 */
			}
			if (zhuaHandlerCountDown != null) {
				try {
					zhuaHandlerCountDown.await();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					// 记录错误
					e.printStackTrace();
				}
			}
			log.info("下载完成，总计时间：" + (System.currentTimeMillis() - startTime));
		} finally {
			client.getConnectionManager().shutdown();
		}
	}

	class ZhuaHandler implements Runnable {

		private HttpClient client;
		private List<String> urlList;
		private String path;

		public ZhuaHandler(HttpClient client, List<String> urlList, String path) {
			// TODO Auto-generated constructor stub
			this.client = client;
			this.urlList = urlList;
			this.path = path;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			try {
				zhua();
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			} finally {
				// 线程减数
				if (zhuaHandlerCountDown != null) {
					zhuaHandlerCountDown.countDown();
				}
			}
		}

		public void zhua() {
			for (Iterator<String> iterator = urlList.iterator(); iterator
					.hasNext();) {
				String string = iterator.next();
				if (!saveContent(client, string, path)) {
					log.warn("下载失败：" + string);
				}
			}
		}

	}

}